[Top] [Prev] [Next] [Bottom] [Contents]

FUNCTION Object Implementation

Sapphire/Web offers the ability to integrate user objects into its framework. The Table Component Object uses one such technique by building a customizable component out of a Sapphire/Web API, allowing any developer to use it with one function call. A similar technique allows you to use your existing APIs. In addition, you can integrate objects using data site callbacks. A final technique, described in this section, is the use of FUNCTION object definitions using the Object Editor and the FUNCTION object implementation set of functions, "SaReq...".

Here is an example of using FUNCTION objects. The relevant files can be found in the contrib/func directory of the Sapphire/Web distribution.

Make a new directory, copy in the files, and type saweb. Select Tools|Object Editor... at the Project Window screen. At the Object Editor menu, select File|New. Select FUNC as the Object type. Enter ECHO_TWO_ARGS in the selection textfield and press OK. Enter EchoArgs in the Function Name textbox. Enter LastName in the Function Arguments Name textfield and press the associated Add button.

Repeat for another function argument name, FirstName. Now Enter, Salute, in the Column Name text box. Press the associated Add button. Repeat for two more columns, LName and FName. At the Object Editor screen, select File|Save. Close the Object Editor.

At this point, you have a FUNCTION object. Now let's develop a CGI to use it. Add the two HTML files, finsert.html and fresults.html, to your project. From the Project Window, select Document Manager, then select Edit|Options. Under the Makefile category, add SaEchoArgs.o to the $SA_APPL_OBJS option. This object file will be derived from the file, SaEchoArgs.c which has the implementation of the function, EchoArgs.

Under the Project Category, set the start-up HTML file to be finsert.html. Press Ok to save these options.

At the Project Window, select Tools|Object Bind Editor... from the project menu. For the Activator choose finsert.html and the form TwoArgs. Press Ok. At Object Type, chose FUNC. Select ECHO_TWO_ARGS from the list and press Ok.

Now bind LastName to LastName and FirstName to FirstName in the arguments section. Choose fresults.html as the result template. Bind all 3 columns to the RESULTS Data Site. Bring up the Results Detail Dialog Box. Select SaPopulateTable as the callback. Press Ok. Now Press Ok in the Object Bind Editor.

Register the function object implementation by opening the Project Window and selecting Edit|Project Code... . In the "Includes, Defines, Global Variables" text box, enter the code:

#include "SaEchoArgs.h"
Make sure you enter a return after this one line.

In the "Main Function Initial Code" textbox, enter the code:

SaRegisterObjImp("EchoArgs", EchoArgs);
Make sure you enter a return after this one line. Press OK. Now save, build, and test your project. Enter your last name and first name in the first form then press the corresponding Insert button.

Now you will define another FUNC Object which will also use the EchoArgs function implementation. Choose Tools|Object Editor ... from the project window menu. Choose File|New in the Object Editor menu. Select FUNC as the Object type. Enter ECHO_THREE_ARGS in the selection textfield and press Ok. Enter EchoArgs in the Function Name textbox. Enter LastName in the Function Arguments Name textfield and press the associated Add button. Repeat for other function argument names, FirstName and Other. Now Enter, Salute, in the Column Name text box. Press the associated Add button. Repeat for 2 more columns, LName, FName, and More. Now choose File|Save from the Object Editor menu. Close the Object Editor.

At this point, you have a second FUNCTION object. Now choose Tools|Object Bind Editor... from the project menu. For the activator choose finsert.html and the ThreeArgs form. Press Ok. Choose FUNC as the type in the Object Selector. Select ECHO_TWO_ARGS from the list and press Ok. Now bind LastName to LastName, FirstName to FirstName, and Other to Other in the arguments section. Choose fresults.html as the result template. Bind all 4 columns to the RESULTS data site. Bring up the Results Column Detail Editor. Select SaPopulateTable as the callback. Press Ok. Now Press Ok in the Object Bind Editor. Now save, build, and test your project. Enter your last name, first name, and other information in the second form then press the corresponding Insert button. You should reload this start-up document in your browser to get the updated HTML file contents.

The code for the EchoArgs is shown below:

#include "SaRnHtml.h"

#ifdef _NO_PROTO
int EchoArgs(p)
pSgeWorkCallData p;
#else
int EchoArgs(pSgeWorkCallData p)
#endif
{
    int i, size;
    char* value;
    char* name;
    pSutList options;
    char* str;

    if (!p)
    {
        return 0;
  }

/*** DO NOT MODIFY list or its contents, read-only. ***/
	options = SaReqGetOptionList(p);
	size = SaReqGetNumArgs(p);

	if (size == 0)
    {
        SaReqSetErrorCode(p, 1);
        SaReqSetReturnCode(p, 1);
        SaReqSetAffectedRowCount(p, 0);
        SaReqAppendError(p, SGEGENERIC,0,0, 
						"EchoArgs : No 			 args found", 0, 0);
        return 0;
    }

    SaReqAppendString(p, "Hello");
    for(i=0; i<size; i++)
    {
        /**** DO NOT MODIFY, read-only data ****/
        value = SaReqGetNArg(p, i);
        /**** DO NOT MODIFY, read-only data ****/
        name = SaReqGetNArgName(p, i);

        str = (char*) malloc(strlen(name) + strlen(value)
				+ 2);
        sprintf(str, "%s=%s", name, value);
	SaReqAppendString(p, str);
        /**** SaReqAppendString copies in string ****/
        free(str);

        /**** DO NOT MODIFY, read-only data ****/
        /**** example, not used here *****/
        value = SaReqGetArgByName(p, name);
    }
	SaReqSetGroupCount(p, 1);
    SaReqAppendRowCount(p, 1);
    SaReqAppendColCount(p, size+1);

    SaReqSetErrorCode(p, 0);
    SaReqSetReturnCode(p, 0);
    SaReqSetAffectedRowCount(p, 1);

    return 1;
}
EchoArgs checks for the presence of arguments. If there are none, the function sets appropriate error flags, messages and returns. The function then finds the number of arguments, their values, and their names. It even gets the value by name. In normal development you do not need to do this multiple ways; it is just for illustration purposes. The application then adds return strings based on the argument values and names. After processing each argument, the function sets the group count (always 1 in this version of Sapphire/Web), and the column and row counts. This function always returns one row with the number of columns equal to the number of arguments plus one for the "Hello" string. It then sets the error and return codes as well as the affected row count.

1. The previous example may at first appear time-consuming. However, there are real benefits to defining and implementing FUNCTION objects. Once defined and implemented, you and all others on a project can use Function Objects with just point and click. You can build the implementations into one library, have one function to register all implementations, add a call to that function in the main.tem file, then add the implementation library to the Makefile.tem for the whole tool to make it even easier.

2. The FUNCTION object can now participate in all the Population callbacks since that object is now a first class citizen.

3. The argument processing API in your function can handle arguments by name and also can process a variable number of arguments as the example has shown.

4. It is possible to design a FUNCTION object implementation which wraps up a C++ class and uses an argument to determine which method to execute. Users are effectively calling an interpretive C++ language with their client browser,.



[Top] [Prev] [Next] [Bottom] [Contents]

info@bluestone.com
Copyright © 1997, Bluestone. All rights reserved.